import logging
from typing import Dict, Any, List
from langchain.schema import BaseMessage, HumanMessage, SystemMessage
from .base_model import BaseLLMModel
from config import Config

logger = logging.getLogger(__name__)

class RAGModel(BaseLLMModel):
    """RAG模型：用于基于检索的问答"""
    
    def __init__(self, model_name: str = None, temperature: float = 0.7):
        super().__init__(model_name, temperature)
        self._setup_rag_prompt()
    
    def _setup_rag_prompt(self):
        """设置RAG提示词模板"""
        self.rag_system_prompt = """你是一位专业的代码规范检查与优化助手，负责审查 Git diff 获取的内容是否符合公司代码标准。你精通公司代码规范与 commit message 规范，理解开发节奏，以鼓励通过为主要目标，避免因小问题反复打回，降低开发体验。

你的核心能力包括：
代码规范检查：基于提供的代码规范文档，检查 Git diff 是否存在规范问题；如果内容过长出现截断导致部分语法错误，不考虑截断导致的语法问题；非关键性问题不影响 pass，但应提醒；完全符合代码规范时 reason 留空。
提交信息生成：输出符合公司提交规范的 commit message，必须遵循标准 Git commit 格式：
- 格式：`<type>(<scope>): <subject>`
- type 类型：feat（新功能）、fix（修复）、docs（文档）、style（格式）、refactor（重构）、test（测试）、chore（构建）
- scope 范围：可选，表示影响范围（如：api、ui、auth等）
- subject 主题：简短描述，不超过50个字符，使用中文
- 示例：`feat(api): 添加用户认证接口`、`fix(ui): 修复登录页面样式问题`
代码优化建议：如为不通过，需给出明确、可操作的优化建议；若为通过但存在小问题，可留空或轻量提示建议。

## 输出格式（必须使用以下 JSON 结构）：
{
"pass": true/false,
"reason": "不通过时请列出具体原因；通过但存在小问题时可温和提示；完全符合请为空",
"commitMessage": "符合规范的 commit message（若 pass 为 false，此字段应为空）",
"optimizationSuggestion": "仅当 pass 为 false 时提供修改建议；若 pass 为 true 则为空或省略"
}

## 重要说明：
1. 必须严格按照上述JSON格式输出，所有字段都必须存在
2. 字段名必须完全匹配：pass, reason, commitMessage, optimizationSuggestion
3. pass字段必须是布尔值：true 或 false
4. 其他字段必须是字符串类型
5. 如果pass为false，commitMessage字段必须为空字符串
6. 如果pass为true，optimizationSuggestion字段可以为空字符串或省略

限制说明：
必须严格按照提供的代码规范文档进行审查，将 Git diff 内容与规范文档进行对比分析。
如果检索到相关规范文档，必须基于这些文档的具体要求来判断代码是否符合规范。
如果未检索到相关规范文档，则基于通用的代码规范进行判断。
避免代码中出现规范文档中严格禁止的行为。
如果存在已截断代码，则已截断部分代码可以不用考虑。
commit message 语义清晰，reason 简明扼要，优化建议可操作。"""
    
    def _extract_search_keywords(self, git_diff: str, user_id: str = None, session_id: str = None) -> str:
        """从git diff中提取检索关键词"""
        # 确保logger可用
        import logging
        local_logger = logging.getLogger(__name__)
        
        try:
            local_logger.info(f"🔍 开始提取关键词，git_diff长度: {len(git_diff)}")
            local_logger.info(f"👤 追踪参数 - user_id: {user_id}, session_id: {session_id}")
            
            # 构建关键词提取的提示词
            keyword_prompt = f"""请从以下Git diff中提取用于检索代码规范文档的关键词。重点关注：
1. 编程语言（如Python、JavaScript、Java等）
2. 代码结构（如函数、类、变量、导入等）
3. 代码模式（如异常处理、循环、条件判断等）
4. 文件类型（如.py、.js、.java等）
5. 框架或库（如React、Django、Spring等）

请返回7-10个最重要的关键词，用空格分隔。

Git diff内容：
{git_diff}

关键词："""
            
            local_logger.info(f"📝 构建关键词提取提示词")
            messages = self._create_messages(
                system_prompt="你是一个专业的代码分析助手，擅长从代码变更中提取关键信息。请提取最相关的关键词用于检索相关规范文档。",
                user_prompt=keyword_prompt
            )
            
            # 传递追踪参数
            local_logger.info(f"🚀 调用LLM提取关键词")
            response = self._invoke_with_langfuse(
                messages, 
                user_id=user_id, 
                session_id=session_id
            )
            keywords = response.content if hasattr(response, 'content') else str(response)
            
            # 清理关键词，确保格式正确
            keywords = keywords.strip()
            if not keywords or keywords.lower() in ['无', 'none', 'null', '']:
                # 如果无法提取关键词，使用默认关键词
                keywords = "代码规范 编码标准 开发规范"
                local_logger.warning(f"⚠️ 无法提取关键词，使用默认关键词")
            
            local_logger.info(f"✅ 从git diff中提取的关键词: {keywords}")
            return keywords
            
        except Exception as e:
            local_logger.error(f"❌ 关键词提取失败: {str(e)}，使用默认关键词")
            return "代码规范 编码标准 开发规范"
    
    def generate_response(self, question: str, context: str, user_id: str = None, session_id: str = None) -> str:
        """基于上下文生成回答"""
        # 确保logger可用
        import logging
        local_logger = logging.getLogger(__name__)
        
        try:
            local_logger.info(f"🤖 RAGModel.generate_response 开始")
            local_logger.info(f"📝 问题: {question}")
            local_logger.info(f"📋 上下文长度: {len(context)} 字符")
            local_logger.info(f"📋 上下文预览: {context[:300]}...")
            local_logger.info(f"👤 追踪参数 - user_id: {user_id}, session_id: {session_id}")
            
            # 构建用户消息，包含上下文和问题
            user_message = f"""请根据上述角色定义、核心能力、输出格式及限制说明，结合提供的代码规范文档和 Git diff 内容进行综合分析和判断。

## 代码规范文档（请严格按照这些规范进行审查）：
{context}

## Git diff 内容（需要审查的代码变更）：
{question}

## 输出要求：
请将 Git diff 内容与代码规范文档进行对比分析，判断代码是否符合规范要求，并严格按照指定的JSON格式输出结果。确保所有字段都存在且格式正确。"""
            
            # 创建消息
            messages = self._create_messages(
                system_prompt=self.rag_system_prompt,
                user_prompt=user_message
            )
            
            # 生成回答 - 使用Langfuse追踪，传递追踪参数
            local_logger.info(f"🚀 调用 _invoke_with_langfuse，传递参数 - user_id: {user_id}, session_id: {session_id}")
            response = self._invoke_with_langfuse(
                messages, 
                user_id=user_id, 
                session_id=session_id
            )
            
            answer = response.content if hasattr(response, 'content') else str(response)
            
            local_logger.info(f"✅ 回答生成完成，长度: {len(answer)}")
            local_logger.info(f"📄 回答内容: {answer}")
            
            return answer
            
        except Exception as e:
            local_logger.error(f"❌ 生成回答时发生错误: {str(e)}")
            return self._handle_error(e, "生成回答")
    
    def check_code_standards(self, git_diff: str, rag_system=None, user_id: str = None, session_id: str = None) -> Dict[str, Any]:
        """代码规范检查 - 支持RAG检索"""
        # 确保logger可用
        import logging
        local_logger = logging.getLogger(__name__)
        
        try:
            local_logger.info(f"🔍 开始代码规范检查，diff长度: {len(git_diff)}")
            local_logger.info(f"👤 追踪参数 - user_id: {user_id}, session_id: {session_id}")
            
            # 如果有RAG系统，先检索相关规范文档
            context = ""
            if rag_system:
                try:
                    # 从git diff中提取检索关键词，传递追踪参数
                    search_keywords = self._extract_search_keywords(
                        git_diff, 
                        user_id=user_id, 
                        session_id=session_id
                    )
                    
                    # 检索相关的代码规范文档
                    # 直接使用文档处理器进行检索，不生成回答
                    relevant_docs_with_scores = rag_system.document_processor.search_similar_with_score(
                        search_keywords, 
                        "default", 
                        5
                    )
                    
                    # 分离文档和分数
                    relevant_docs = [doc for doc, score in relevant_docs_with_scores]
                    doc_scores = [score for doc, score in relevant_docs_with_scores]
                    
                    if relevant_docs:
                        # 构建检索结果
                        retrieval_result = {
                            "status": "success",
                            "sources": []
                        }
                        
                        # 构建源文档信息
                        for i, doc in enumerate(relevant_docs):
                            source_info = {
                                "source": doc.metadata.get("source", "未知来源"),
                                "file_name": doc.metadata.get("file_name", "未知文件"),
                                "file_type": doc.metadata.get("file_type", "未知类型"),
                                "content_preview": doc.page_content[:200] + "..." if len(doc.page_content) > 200 else doc.page_content,
                                "similarity": doc_scores[i] if i < len(doc_scores) else None
                            }
                            retrieval_result["sources"].append(source_info)
                    else:
                        retrieval_result = {
                            "status": "warning",
                            "sources": []
                        }
                    
                    if retrieval_result.get("status") == "success" and retrieval_result.get("sources"):
                        # 构建上下文
                        context_parts = []
                        retrieved_docs = []
                        for source in retrieval_result["sources"]:
                            context_parts.append(f"规范文档: {source['content_preview']}")
                            # 保存检索到的文档信息
                            retrieved_docs.append({
                                "title": source.get("file_name", "未知标题"),
                                "content": source.get("content_preview", ""),
                                "similarity": source.get("similarity", 0.0)
                            })
                        context = "\n".join(context_parts)
                        local_logger.info(f"📚 检索到 {len(retrieval_result['sources'])} 个相关规范文档")
                    else:
                        local_logger.warning("⚠️ 未检索到相关规范文档，将使用默认检查")
                        retrieved_docs = []
                        
                except Exception as e:
                    local_logger.warning(f"⚠️ RAG检索失败: {str(e)}，将使用默认检查")
            
            # 构建用户消息
            if context:
                user_message = f"""请根据上述角色定义、核心能力、输出格式及限制说明，结合提供的代码规范文档和 Git diff 内容进行综合分析和判断。

## 代码规范文档（请严格按照这些规范进行审查）：
{context}

## Git diff 内容（需要审查的代码变更）：
{git_diff}

## 输出要求：
请将 Git diff 内容与代码规范文档进行对比分析，判断代码是否符合规范要求，并严格按照指定的JSON格式输出结果。确保所有字段都存在且格式正确。"""
            else:
                user_message = f"""请根据上述角色定义、核心能力、输出格式及限制说明，对 Git diff 获取的内容进行代码规范检查、生成符合要求的 commit message（如适用）并提供优化建议（如适用），输出完整的 JSON 对象。

## Git diff 内容：
{git_diff}

## 输出要求：
注意：由于未检索到相关规范文档，请基于通用的代码规范进行判断。请严格按照指定的JSON格式输出结果。"""
            
            # 创建消息
            messages = self._create_messages(
                system_prompt=self.rag_system_prompt,
                user_prompt=user_message
            )
            
            # 生成回答，传递追踪参数
            response = self._invoke_with_langfuse(
                messages, 
                user_id=user_id, 
                session_id=session_id
            )
            
            answer = response.content if hasattr(response, 'content') else str(response)
            
            # 尝试解析JSON
            import json
            try:
                result = json.loads(answer)
                local_logger.info(f"✅ 代码规范检查完成，结果: {result.get('pass', 'unknown')}")
                
                # 添加检索到的文档信息到结果中
                if 'retrieved_docs' in locals():
                    result['retrieved_documents'] = retrieved_docs
                else:
                    result['retrieved_documents'] = []
                
                return result
            except json.JSONDecodeError:
                local_logger.warning(f"⚠️ JSON解析失败，原始回答: {answer}")
                return {
                    "pass": False,
                    "reason": "JSON格式解析失败",
                    "commitMessage": "",
                    "optimizationSuggestion": "请检查AI回答的JSON格式是否正确"
                }
            
        except Exception as e:
            local_logger.error(f"❌ 代码规范检查时发生错误: {str(e)}")
            return {
                "pass": False,
                "reason": f"检查过程中发生错误: {str(e)}",
                "commitMessage": "",
                "optimizationSuggestion": "请重试或检查系统配置"
            }
    
    def generate_summary(self, text: str, max_length: int = 200, user_id: str = None, session_id: str = None) -> str:
        """生成文本摘要"""
        try:
            summary_prompt = f"""请为以下文本生成一个简洁的摘要，摘要长度不超过{max_length}个字符：

{text}

摘要："""
            
            messages = self._create_messages(
                system_prompt="你是一个专业的文本摘要助手，请生成简洁、准确的摘要。",
                user_prompt=summary_prompt
            )
            
            response = self._invoke_with_langfuse(
                messages, 
                user_id=user_id, 
                session_id=session_id
            )
            summary = response.content if hasattr(response, 'content') else str(response)
            
            return summary[:max_length]
            
        except Exception as e:
            # 确保logger可用
            import logging
            local_logger = logging.getLogger(__name__)
            local_logger.error(f"❌ 生成摘要时发生错误: {str(e)}")
            return self._handle_error(e, "生成摘要")
    
    def analyze_sentiment(self, text: str, user_id: str = None, session_id: str = None) -> Dict[str, Any]:
        """分析文本情感"""
        try:
            sentiment_prompt = f"""请分析以下文本的情感倾向，并返回JSON格式的结果：

文本：{text}

请返回以下格式的JSON：
{{
    "sentiment": "positive/negative/neutral",
    "confidence": 0.0-1.0,
    "keywords": ["关键词1", "关键词2"],
    "explanation": "简要说明"
}}"""
            
            messages = self._create_messages(
                system_prompt="你是一个专业的情感分析助手，请返回JSON格式的分析结果。",
                user_prompt=sentiment_prompt
            )
            
            response = self._invoke_with_langfuse(
                messages, 
                user_id=user_id, 
                session_id=session_id
            )
            result = response.content if hasattr(response, 'content') else str(response)
            
            # 尝试解析JSON（简化处理）
            import json
            try:
                return json.loads(result)
            except:
                return {
                    "sentiment": "neutral",
                    "confidence": 0.5,
                    "keywords": [],
                    "explanation": result
                }
                
        except Exception as e:
            # 确保logger可用
            import logging
            local_logger = logging.getLogger(__name__)
            local_logger.error(f"❌ 情感分析时发生错误: {str(e)}")
            return {
                "sentiment": "neutral",
                "confidence": 0.0,
                "keywords": [],
                "explanation": self._handle_error(e, "情感分析")
            } 